// 知识点1：const_cast<type_id> (expression)
// 该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外，
// type_id和expression的类型是一样的。
// 一、常量指针被转化成非常量的指针，并且仍然指向原来的对象；(本例中用到)
// 二、常量引用被转换成非常量的引用，并且仍然指向原来的对象；
// 三、const_cast一般用于修改底指针。如const char *p形式。

// 知识点2：别怕烦，动手写！
#ifndef STRVEC_H
#define STRVEC_H

#include <algorithm>
#include <memory>
#include <string>

using namespace std;

class String {
public:
  String(); //默认构造函数
  //接受c风格字符串参数的构造函数，s为指向字符串的指针(首位置)
  String(const char *s) {
    auto s1 = const_cast<char *>(s); //转化为非常量的指针
    while (*s1) {
      ++s1; //使其指向最后一个位置的尾部
    }
    alloc_n_copy(s, s1); //进行拷贝
  }
  String(const String &);            //拷贝构造函数
  String &operator=(const String &); //拷贝赋值运算符
  //析构函数
  ~String() { free(); }
  //释放内存
  void free() {
    if (elements) {
      for_each(elements, end, [this](char &rhs) { alloc.destroy(&rhs); });
      alloc.deallocate(elements, end - elements);
    }
  }

private:
  allocator<char> alloc; //分配内存的方法
  char *elements;        //首尾指针
  char *end;
  //拷贝赋值函数
  std::pair<char *, char *> alloc_n_copy(const char *a, const char *b) {
    auto s1 = alloc.allocate(b - a); // allocate参数为分配内存的大小
    //拷贝赋值，将a到b之间的元素拷贝至s1,返回的是最后一个构造元素之后的位置
    auto s2 = uninitialized_copy(a, b, s1);
    return make_pair(s1, s2); //返回首尾指针
  }

  void range_initializer(const char *c, const char *d) //初始化
  {
    auto p = alloc_n_copy(d, c); //拷贝并初始化新的string
    elements = p.first;
    end = p.second; //将新的string的首尾指针赋值
  }
};
#endif